package com.winter.common.dynamic.datasource.service.impl;

import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.p6spy.engine.spy.P6DataSource;
import com.winter.common.dynamic.datasource.DynamicRoutingDataSource;
import com.winter.common.dynamic.datasource.service.DataSourceService;
import io.seata.rm.datasource.DataSourceProxy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
@Service
@Slf4j
public class DataSourceServiceImpl implements DataSourceService {
    @Autowired
    private DynamicDataSourceProperties properties;
    @Autowired
    private DataSourceCreator dataSourceCreator;

    @Autowired
    private DynamicRoutingDataSource dynamicRoutingDataSource;
    @Override
    public Map listCurrentDataSource() {
//        Map<String, DataSource> dataSourceMap = this.dynamicRoutingDataSource.getDataSourceMap();
        return this.properties.getDatasource();
    }

    @Override
    public boolean addDataSource(DataSourceProperty dataSourceProperty) {
        DataSource dataSource = this.dataSourceCreator.createDataSource(dataSourceProperty);
        Map<String, DataSourceProperty> map = this.properties.getDatasource();
        dynamicRoutingDataSource.addDataSource(dataSourceProperty.getPollName(),dataSource);
        map.put(dataSourceProperty.getPollName(),dataSourceProperty);
        return true;
    }

    @Override
    public boolean removeDataSource(String alias) throws NoSuchFieldException, IllegalAccessException {
        DataSourceProperty dataSourceProperty = this.properties.getDatasource().get(alias);
        DataSource dataSource = (DataSource)dynamicRoutingDataSource.getDataSourceMap().get(alias);
        if (dynamicRoutingDataSource.getSeata()) {
            DataSourceProxy dataSourceProxy = (DataSourceProxy)dataSource;
            dataSource = dataSourceProxy.getTargetDataSource();
        }

        if (dynamicRoutingDataSource.getP6spy()) {
            Field realDataSourceField = P6DataSource.class.getDeclaredField("realDataSource");
            realDataSourceField.setAccessible(true);
            dataSource = (DataSource)realDataSourceField.get(dataSource);
        }

        Class clazz = dataSource.getClass();

        try {
            Method closeMethod = clazz.getDeclaredMethod("close");
            closeMethod.invoke(dataSource);
        } catch (NoSuchMethodException | InvocationTargetException var6) {
            log.warn("dynamic-datasource close the datasource named [{}] failed,", alias);
        }
        return false;
    }

    @Override
    public DataSourceProperty defaultDataSource() {
        this.properties.getPrimary();
        String primary = dynamicRoutingDataSource.getPrimary();
        return this.properties.getDatasource().get(primary);
    }
    public DataSourceProperty currentDataSource(){
        String current = DynamicDataSourceContextHolder.peek();
        return this.properties.getDatasource().get(current);
    }
    @Override
    public boolean setDefaultDataSource(String alias) {
        Map<String, DataSourceProperty> map = this.properties.getDatasource();
        if(!map.containsKey(alias)){
            return false;
        }
        dynamicRoutingDataSource.setPrimary(alias);
        this.properties.setPrimary(alias);
        return true;
    }

}
